package com.lap.context.starter.handler;

import com.lap.context.starter.entity.HeaderInfo;
import java.util.function.Function;
import java.util.function.Supplier;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@UtilityClass
public class UserHandler {

  private static final ThreadLocal<HeaderInfo> THREAD_LOCAL = new ThreadLocal<>();

  /**
   * 设置当前线程的用户上下文信息
   *
   * @param context 用户上下文信息，为null时将清除现有上下文
   */
  public static void set(HeaderInfo context) {
    if (context == null) {
      remove();
    } else {
      THREAD_LOCAL.set(context);
    }
  }

  /**
   * 获取当前线程的用户上下文信息
   *
   * @return 用户上下文信息，可能为null
   */
  public static HeaderInfo get() {
    return THREAD_LOCAL.get();
  }

  /** 清除当前线程的用户上下文信息 */
  public static void remove() {
    THREAD_LOCAL.remove();
  }

  /** 获取用户ID，失败时返回null */
  public static Integer getUserId() {
    return getValue(HeaderInfo::getUserId);
  }

  /** 获取用户名，失败时返回系统用户 */
  public static String getUserName() {
    return getValue(HeaderInfo::getUserName);
  }

  /** 获取用户名 * */
  public static String getFullName() {
    return getValue(HeaderInfo::getFullName);
  }

  /** 获取租户 */
  public static String getTenantCode() {
    return getValue(HeaderInfo::getTenantCode);
  }

  /**
   * 安全获取上下文属性，若获取失败返回默认值
   *
   * @param extractor 属性提取函数
   * @return 上下文属性值或默认值
   */
  public static <T> T getValue(Function<HeaderInfo, T> extractor) {
    HeaderInfo header = get();
    if (header != null) {
      return extractor.apply(header);
    }
    return null;
  }

  /** 使用资源管理模式管理用户上下文 确保在执行任务后自动清理上下文，避免内存泄漏 */
  public static void withContext(HeaderInfo context, Runnable task) {
    set(context);
    try {
      task.run();
    } finally {
      remove();
    }
  }

  /** 使用资源管理模式管理用户上下文（带返回值版本） */
  public static <T> T withContext(HeaderInfo context, Supplier<T> task) {
    set(context);
    try {
      return task.get();
    } finally {
      remove();
    }
  }
}
